package javasec.contempt.data;

import java.lang.reflect.Method;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javasec.contempt.consoles.SeedNotificationConsole;
import javasec.contempt.data.SeedNotifier;

import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IConsole;


public class SeedNotifier extends UnicastRemoteObject
{
	// wow, all that got ugly fast TODO  maybe make a special class someday?
	public Map<String,ArrayList<Method>> methodHash=new HashMap<String,ArrayList<Method>>();
	public Map<String,ArrayList<Object>> instanceHash=new HashMap<String,ArrayList<Object>>();
	public SeedNotifier instance=null;
	
	SeedNotificationConsole console=new SeedNotificationConsole("notifications",null);
	
	protected SeedNotifier() throws RemoteException
	{
		super();
		if(instance==null)instance=this;
		
		// create a console to watch notifications
		ConsolePlugin.getDefault().getConsoleManager().addConsoles(new IConsole[] {console});
	}
	
	// The seed server calls this function to let javasec.contempt
	// know what is going on.
	public void notifyClient(String key, Object data) throws RemoteException
	{
		console.println(key+": "+data);
		
		// look up the ID and invoke the method
		if(!methodHash.containsKey(key))return;
		ArrayList<Method> methodList=methodHash.get(key);
		ArrayList<Object> instanceList=instanceHash.get(key);
		
		for(int x=0;x<methodList.size();++x)
		{
			try
			{
				methodList.get(x).invoke(instanceList.get(x),data);
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}
		}
	}
	
	public boolean subscribe(String key, Object instance, String methodName)
	{
		Method method=null;
		try
		{
			method=instance.getClass().getMethod(methodName,Class.forName("java.lang.Object"));
		}
		catch(Exception e)
		{
			System.out.println("SeedNotifier: callback method not found");
			e.printStackTrace();
			return false;
		}
		
		if(instanceHash.containsKey(key))
		{
			ArrayList<Method> methodList=methodHash.get(key);
			ArrayList<Object> instanceList=instanceHash.get(key);
			
			System.out.println("registering "+key);
			instanceList.add(instance);
			methodList.add(method);
		}
		else
		{
			ArrayList<Method> methodList=new ArrayList<Method>();
			methodList.add(method);
			ArrayList<Object> instanceList=new ArrayList<Object>();
			instanceList.add(instance);
			
			instanceHash.put(key,instanceList);
			methodHash.put(key,methodList);
		}
		
		return true;
	}
}
